import { PrismaClient } from '@prisma/client';
import { createModuleLogger } from '@/utils/logger';
import config from '@/config';

const logger = createModuleLogger('chain-monitor-config');

export interface ChainMonitorConfig {
  id?: number;
  chain: string;
  isEnabled: boolean;
  rpcUrl: string;
  wssUrl?: string;
  minValueUsd: number;
  blockTime: number;
  maxRetries: number;
  requestDelay: number;
  batchSize: number;
  fallbackRpcs?: string[];
  chainSettings?: any;
  lastStarted?: Date;
  lastStopped?: Date;
  errorCount: number;
  totalTxCount: number;
}

class ChainMonitorConfigService {
  private static instance: ChainMonitorConfigService;
  private prisma: PrismaClient;

  private constructor() {
    this.prisma = new PrismaClient();
  }

  public static getInstance(): ChainMonitorConfigService {
    if (!ChainMonitorConfigService.instance) {
      ChainMonitorConfigService.instance = new ChainMonitorConfigService();
    }
    return ChainMonitorConfigService.instance;
  }

  // 初始化默认配置
  public async initializeDefaultConfigs(): Promise<void> {
    try {
      logger.info('🔧 初始化默认链监控配置...');

      const defaultConfigs = [
        {
          chain: 'ethereum',
          isEnabled: true,
          rpcUrl: config.chains.ethereum.rpcUrl,
          wssUrl: config.chains.ethereum.wssUrl,
          minValueUsd: config.chains.ethereum.minValueUSD,
          blockTime: config.chains.ethereum.blockTime,
          maxRetries: 3,
          requestDelay: 1000,
          batchSize: 100,
          fallbackRpcs: config.chains.ethereum.fallbackRpcUrls,
          errorCount: 0,
          totalTxCount: 0
        },
        {
          chain: 'bsc',
          isEnabled: true,
          rpcUrl: config.chains.bsc.rpcUrl,
          wssUrl: config.chains.bsc.wssUrl,
          minValueUsd: config.chains.bsc.minValueUSD,
          blockTime: config.chains.bsc.blockTime,
          maxRetries: 3,
          requestDelay: 1000,
          batchSize: 100,
          fallbackRpcs: [],
          errorCount: 0,
          totalTxCount: 0
        },
        {
          chain: 'bitcoin',
          isEnabled: true,
          rpcUrl: config.chains.bitcoin.rpcUrl,
          wssUrl: undefined,
          minValueUsd: config.chains.bitcoin.minValueUSD,
          blockTime: config.chains.bitcoin.blockTime,
          maxRetries: 3,
          requestDelay: 2000,
          batchSize: 50,
          fallbackRpcs: [],
          errorCount: 0,
          totalTxCount: 0
        }
      ];

      for (const configData of defaultConfigs) {
        await this.prisma.chainMonitorConfig.upsert({
          where: { chain: configData.chain },
          update: {
            // 只更新RPC相关信息，保留用户自定义的设置
            rpcUrl: configData.rpcUrl,
            wssUrl: configData.wssUrl,
            fallbackRpcs: configData.fallbackRpcs,
            updatedAt: new Date()
          },
          create: configData
        });
      }

      logger.info('✅ 默认链监控配置初始化完成');
    } catch (error) {
      logger.error('❌ 初始化默认配置失败:', error);
      throw error;
    }
  }

  // 获取单个链配置
  public async getChainConfig(chain: string): Promise<ChainMonitorConfig | null> {
    try {
      const config = await this.prisma.chainMonitorConfig.findUnique({
        where: { chain }
      });

      if (!config) return null;

      return {
        ...config,
        minValueUsd: Number(config.minValueUsd),
        fallbackRpcs: config.fallbackRpcs as string[] || []
      };
    } catch (error) {
      logger.error(`获取 ${chain} 配置失败:`, error);
      return null;
    }
  }

  // 获取所有链配置
  public async getAllChainConfigs(): Promise<ChainMonitorConfig[]> {
    try {
      const configs = await this.prisma.chainMonitorConfig.findMany({
        orderBy: { chain: 'asc' }
      });

      return configs.map(config => ({
        ...config,
        minValueUsd: Number(config.minValueUsd),
        fallbackRpcs: config.fallbackRpcs as string[] || []
      }));
    } catch (error) {
      logger.error('获取所有链配置失败:', error);
      return [];
    }
  }

  // 获取启用的链配置
  public async getEnabledChainConfigs(): Promise<ChainMonitorConfig[]> {
    try {
      const configs = await this.prisma.chainMonitorConfig.findMany({
        where: { isEnabled: true },
        orderBy: { chain: 'asc' }
      });

      return configs.map(config => ({
        ...config,
        minValueUsd: Number(config.minValueUsd),
        fallbackRpcs: config.fallbackRpcs as string[] || []
      }));
    } catch (error) {
      logger.error('获取启用链配置失败:', error);
      return [];
    }
  }

  // 更新链配置
  public async updateChainConfig(chain: string, updates: Partial<ChainMonitorConfig>): Promise<boolean> {
    try {
      await this.prisma.chainMonitorConfig.update({
        where: { chain },
        data: {
          ...updates,
          updatedAt: new Date()
        }
      });

      logger.info(`✅ ${chain} 配置已更新`, updates);
      return true;
    } catch (error) {
      logger.error(`❌ 更新 ${chain} 配置失败:`, error);
      return false;
    }
  }

  // 启用/禁用链监控
  public async setChainEnabled(chain: string, enabled: boolean): Promise<boolean> {
    try {
      const timestamp = new Date();
      await this.prisma.chainMonitorConfig.update({
        where: { chain },
        data: {
          isEnabled: enabled,
          lastStarted: enabled ? timestamp : undefined,
          lastStopped: enabled ? undefined : timestamp,
          updatedAt: timestamp
        }
      });

      logger.info(`✅ ${chain} 监控已${enabled ? '启用' : '禁用'}`);
      return true;
    } catch (error) {
      logger.error(`❌ ${enabled ? '启用' : '禁用'} ${chain} 监控失败:`, error);
      return false;
    }
  }

  // 更新错误计数
  public async incrementErrorCount(chain: string): Promise<void> {
    try {
      await this.prisma.chainMonitorConfig.update({
        where: { chain },
        data: {
          errorCount: { increment: 1 },
          updatedAt: new Date()
        }
      });
    } catch (error) {
      logger.error(`更新 ${chain} 错误计数失败:`, error);
    }
  }

  // 更新交易计数
  public async incrementTxCount(chain: string, count: number = 1): Promise<void> {
    try {
      await this.prisma.chainMonitorConfig.update({
        where: { chain },
        data: {
          totalTxCount: { increment: count },
          updatedAt: new Date()
        }
      });
    } catch (error) {
      logger.error(`更新 ${chain} 交易计数失败:`, error);
    }
  }

  // 重置错误计数
  public async resetErrorCount(chain: string): Promise<void> {
    try {
      await this.prisma.chainMonitorConfig.update({
        where: { chain },
        data: {
          errorCount: 0,
          updatedAt: new Date()
        }
      });
    } catch (error) {
      logger.error(`重置 ${chain} 错误计数失败:`, error);
    }
  }

  // 关闭数据库连接
  public async disconnect(): Promise<void> {
    await this.prisma.$disconnect();
  }
}

export default ChainMonitorConfigService; 